home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / nose / util.py < prev   
Text File  |  2009-05-13  |  20KB  |  672 lines

  1. """Utility functions and classes used by nose internally.
  2. """
  3. import inspect
  4. import itertools
  5. import logging
  6. import os
  7. import re
  8. import sys
  9. import types
  10. import unittest
  11. from types import ClassType, TypeType
  12.  
  13. try:
  14.     from compiler.consts import CO_GENERATOR
  15. except ImportError:
  16.     # IronPython doesn't have a complier module
  17.     CO_GENERATOR=0x20
  18.     
  19. log = logging.getLogger('nose')
  20.  
  21. ident_re = re.compile(r'^[A-Za-z_][A-Za-z0-9_.]*$')
  22. class_types = (ClassType, TypeType)
  23. skip_pattern = r"(?:\.svn)|(?:[^.]+\.py[co])|(?:.*~)|(?:.*\$py\.class)"
  24.  
  25. try:
  26.     set()
  27.     set = set # make from nose.util import set happy
  28. except NameError:
  29.     try:
  30.         from sets import Set as set
  31.     except ImportError:
  32.         pass
  33.  
  34.  
  35. def ls_tree(dir_path="",
  36.             skip_pattern=skip_pattern,
  37.             indent="|-- ", branch_indent="|   ",
  38.             last_indent="`-- ", last_branch_indent="    "):
  39.     # TODO: empty directories look like non-directory files
  40.     return "\n".join(_ls_tree_lines(dir_path, skip_pattern,
  41.                                     indent, branch_indent,
  42.                                     last_indent, last_branch_indent))
  43.  
  44.  
  45. def _ls_tree_lines(dir_path, skip_pattern,
  46.                    indent, branch_indent, last_indent, last_branch_indent):
  47.     if dir_path == "":
  48.         dir_path = os.getcwd()
  49.  
  50.     lines = []
  51.  
  52.     names = os.listdir(dir_path)
  53.     names.sort()
  54.     dirs, nondirs = [], []
  55.     for name in names:
  56.         if re.match(skip_pattern, name):
  57.             continue
  58.         if os.path.isdir(os.path.join(dir_path, name)):
  59.             dirs.append(name)
  60.         else:
  61.             nondirs.append(name)
  62.  
  63.     # list non-directories first
  64.     entries = list(itertools.chain([(name, False) for name in nondirs],
  65.                                    [(name, True) for name in dirs]))
  66.     def ls_entry(name, is_dir, ind, branch_ind):
  67.         if not is_dir:
  68.             yield ind + name
  69.         else:
  70.             path = os.path.join(dir_path, name)
  71.             if not os.path.islink(path):
  72.                 yield ind + name
  73.                 subtree = _ls_tree_lines(path, skip_pattern,
  74.                                          indent, branch_indent,
  75.                                          last_indent, last_branch_indent)
  76.                 for x in subtree:
  77.                     yield branch_ind + x
  78.     for name, is_dir in entries[:-1]:
  79.         for line in ls_entry(name, is_dir, indent, branch_indent):
  80.             yield line
  81.     if entries:
  82.         name, is_dir = entries[-1]
  83.         for line in ls_entry(name, is_dir, last_indent, last_branch_indent):
  84.             yield line
  85.  
  86.  
  87. def absdir(path):
  88.     """Return absolute, normalized path to directory, if it exists; None
  89.     otherwise.
  90.     """
  91.     if not os.path.isabs(path):
  92.         path = os.path.normpath(os.path.abspath(os.path.join(os.getcwd(),
  93.                                                              path)))
  94.     if path is None or not os.path.isdir(path):
  95.         return None
  96.     return path
  97.  
  98.  
  99. def absfile(path, where=None):
  100.     """Return absolute, normalized path to file (optionally in directory
  101.     where), or None if the file can't be found either in where or the current
  102.     working directory.
  103.     """
  104.     orig = path
  105.     if where is None:
  106.         where = os.getcwd()
  107.     if isinstance(where, list) or isinstance(where, tuple):
  108.         for maybe_path in where:
  109.             maybe_abs = absfile(path, maybe_path)
  110.             if maybe_abs is not None:
  111.                 return maybe_abs
  112.         return None
  113.     if not os.path.isabs(path):
  114.         path = os.path.normpath(os.path.abspath(os.path.join(where, path)))
  115.     if path is None or not os.path.exists(path):
  116.         if where != os.getcwd():
  117.             # try the cwd instead
  118.             path = os.path.normpath(os.path.abspath(os.path.join(os.getcwd(),
  119.                                                                  orig)))
  120.     if path is None or not os.path.exists(path):
  121.         return None
  122.     if os.path.isdir(path):
  123.         # might want an __init__.py from pacakge
  124.         init = os.path.join(path,'__init__.py')
  125.         if os.path.isfile(init):
  126.             return init
  127.     elif os.path.isfile(path):
  128.         return path
  129.     return None
  130.  
  131.  
  132. def anyp(predicate, iterable):
  133.     for item in iterable:
  134.         if predicate(item):
  135.             return True
  136.     return False
  137.  
  138.  
  139. def file_like(name):
  140.     """A name is file-like if it is a path that exists, or it has a
  141.     directory part, or it ends in .py, or it isn't a legal python
  142.     identifier.
  143.     """
  144.     return (os.path.exists(name)
  145.             or os.path.dirname(name)
  146.             or name.endswith('.py')
  147.             or not ident_re.match(os.path.splitext(name)[0]))
  148.  
  149.  
  150. def cmp_lineno(a, b):
  151.     """Compare functions by their line numbers.
  152.  
  153.     >>> cmp_lineno(isgenerator, ispackage)
  154.     -1
  155.     >>> cmp_lineno(ispackage, isgenerator)
  156.     1
  157.     >>> cmp_lineno(isgenerator, isgenerator)
  158.     0
  159.     """
  160.     return cmp(func_lineno(a), func_lineno(b))
  161.  
  162.  
  163. def func_lineno(func):
  164.     """Get the line number of a function. First looks for
  165.     compat_co_firstlineno, then func_code.co_first_lineno.
  166.     """
  167.     try:
  168.         return func.compat_co_firstlineno
  169.     except AttributeError:
  170.         try:
  171.             return func.func_code.co_firstlineno
  172.         except AttributeError:
  173.             return -1
  174.  
  175.  
  176. def isclass(obj):
  177.     """Is obj a class? Inspect's isclass is too liberal and returns True
  178.     for objects that can't be subclasses of anything.
  179.     """
  180.     obj_type = type(obj)
  181.     return obj_type in class_types or issubclass(obj_type, type)
  182.  
  183.  
  184. def isgenerator(func):
  185.     try:
  186.         return func.func_code.co_flags & CO_GENERATOR != 0
  187.     except AttributeError:
  188.         return False
  189. # backwards compat (issue #64)
  190. is_generator = isgenerator
  191.  
  192.  
  193. def ispackage(path):
  194.     """
  195.     Is this path a package directory?
  196.  
  197.     >>> ispackage('nose')
  198.     True
  199.     >>> ispackage('unit_tests')
  200.     False
  201.     >>> ispackage('nose/plugins')
  202.     True
  203.     >>> ispackage('nose/loader.py')
  204.     False
  205.     """
  206.     if os.path.isdir(path):
  207.         # at least the end of the path must be a legal python identifier
  208.         # and __init__.py[co] must exist
  209.         end = os.path.basename(path)
  210.         if ident_re.match(end):
  211.             for init in ('__init__.py', '__init__.pyc', '__init__.pyo'):
  212.                 if os.path.isfile(os.path.join(path, init)):
  213.                     return True
  214.             if sys.platform.startswith('java') and \
  215.                     os.path.isfile(os.path.join(path, '__init__$py.class')):
  216.                 return True
  217.     return False
  218.  
  219.  
  220. def isproperty(obj):
  221.     """
  222.     Is this a property?
  223.  
  224.     >>> class Foo:
  225.     ...     def got(self):
  226.     ...         return 2
  227.     ...     def get(self):
  228.     ...         return 1
  229.     ...     get = property(get)
  230.  
  231.     >>> isproperty(Foo.got)
  232.     False
  233.     >>> isproperty(Foo.get)
  234.     True
  235.     """
  236.     return type(obj) == property
  237.  
  238.  
  239. def getfilename(package, relativeTo=None):
  240.     """Find the python source file for a package, relative to a
  241.     particular directory (defaults to current working directory if not
  242.     given).
  243.     """
  244.     if relativeTo is None:
  245.         relativeTo = os.getcwd()
  246.     path = os.path.join(relativeTo, os.sep.join(package.split('.')))
  247.     suffixes = ('/__init__.py', '.py')
  248.     for suffix in suffixes:
  249.         filename = path + suffix
  250.         if os.path.exists(filename):
  251.             return filename
  252.     return None
  253.  
  254.  
  255. def getpackage(filename):
  256.     """
  257.     Find the full dotted package name for a given python source file
  258.     name. Returns None if the file is not a python source file.
  259.  
  260.     >>> getpackage('foo.py')
  261.     'foo'
  262.     >>> getpackage('biff/baf.py')
  263.     'baf'
  264.     >>> getpackage('nose/util.py')
  265.     'nose.util'
  266.  
  267.     Works for directories too.
  268.  
  269.     >>> getpackage('nose')
  270.     'nose'
  271.     >>> getpackage('nose/plugins')
  272.     'nose.plugins'
  273.  
  274.     And __init__ files stuck onto directories
  275.  
  276.     >>> getpackage('nose/plugins/__init__.py')
  277.     'nose.plugins'
  278.  
  279.     Absolute paths also work.
  280.  
  281.     >>> path = os.path.abspath(os.path.join('nose', 'plugins'))
  282.     >>> getpackage(path)
  283.     'nose.plugins'
  284.     """
  285.     src_file = src(filename)
  286.     if not src_file.endswith('.py') and not ispackage(src_file):
  287.         return None
  288.     base, ext = os.path.splitext(os.path.basename(src_file))
  289.     if base == '__init__':
  290.         mod_parts = []
  291.     else:
  292.         mod_parts = [base]
  293.     path, part = os.path.split(os.path.split(src_file)[0])
  294.     while part:
  295.         if ispackage(os.path.join(path, part)):
  296.             mod_parts.append(part)
  297.         else:
  298.             break
  299.         path, part = os.path.split(path)
  300.     mod_parts.reverse()
  301.     return '.'.join(mod_parts)
  302.  
  303.  
  304. def ln(label):
  305.     """Draw a 70-char-wide divider, with label in the middle.
  306.  
  307.     >>> ln('hello there')
  308.     '---------------------------- hello there -----------------------------'
  309.     """
  310.     label_len = len(label) + 2
  311.     chunk = (70 - label_len) / 2
  312.     out = '%s %s %s' % ('-' * chunk, label, '-' * chunk)
  313.     pad = 70 - len(out)
  314.     if pad > 0:
  315.         out = out + ('-' * pad)
  316.     return out
  317.  
  318.  
  319. def resolve_name(name, module=None):
  320.     """Resolve a dotted name to a module and its parts. This is stolen
  321.     wholesale from unittest.TestLoader.loadTestByName.
  322.  
  323.     >>> resolve_name('nose.util') #doctest: +ELLIPSIS
  324.     <module 'nose.util' from...>
  325.     >>> resolve_name('nose.util.resolve_name') #doctest: +ELLIPSIS
  326.     <function resolve_name at...>
  327.     """
  328.     parts = name.split('.')
  329.     parts_copy = parts[:]
  330.     if module is None:
  331.         while parts_copy:
  332.             try:
  333.                 log.debug("__import__ %s", name)
  334.                 module = __import__('.'.join(parts_copy))
  335.                 break
  336.             except ImportError:
  337.                 del parts_copy[-1]
  338.                 if not parts_copy:
  339.                     raise
  340.         parts = parts[1:]
  341.     obj = module
  342.     log.debug("resolve: %s, %s, %s, %s", parts, name, obj, module)
  343.     for part in parts:
  344.         obj = getattr(obj, part)
  345.     return obj
  346.  
  347.  
  348. def split_test_name(test):
  349.     """Split a test name into a 3-tuple containing file, module, and callable
  350.     names, any of which (but not all) may be blank.
  351.  
  352.     Test names are in the form:
  353.  
  354.     file_or_module:callable
  355.  
  356.     Either side of the : may be dotted. To change the splitting behavior, you
  357.     can alter nose.util.split_test_re.
  358.     """
  359.     norm = os.path.normpath
  360.     file_or_mod = test
  361.     fn = None
  362.     if not ':' in test:
  363.         # only a file or mod part
  364.         if file_like(test):
  365.             return (norm(test), None, None)
  366.         else:
  367.             return (None, test, None)
  368.  
  369.     # could be path|mod:callable, or a : in the file path someplace
  370.     head, tail = os.path.split(test)
  371.     if not head:
  372.         # this is a case like 'foo:bar' -- generally a module
  373.         # name followed by a callable, but also may be a windows
  374.         # drive letter followed by a path
  375.         try:
  376.             file_or_mod, fn = test.split(':')
  377.             if file_like(fn):
  378.                 # must be a funny path
  379.                 file_or_mod, fn = test, None
  380.         except ValueError:
  381.             # more than one : in the test
  382.             # this is a case like c:\some\path.py:a_test
  383.             parts = test.split(':')
  384.             if len(parts[0]) == 1:
  385.                 file_or_mod, fn = ':'.join(parts[:-1]), parts[-1]
  386.             else:
  387.                 # nonsense like foo:bar:baz
  388.                 raise ValueError("Test name '%s' could not be parsed. Please "
  389.                                  "format test names as path:callable or "
  390.                                  "module:callable.")
  391.     elif not tail:
  392.         # this is a case like 'foo:bar/'
  393.         # : must be part of the file path, so ignore it
  394.         file_or_mod = test
  395.     else:
  396.         if ':' in tail:
  397.             file_part, fn = tail.split(':')
  398.         else:
  399.             file_part = tail
  400.         file_or_mod = os.sep.join([head, file_part])
  401.     if file_or_mod:
  402.         if file_like(file_or_mod):
  403.             return (norm(file_or_mod), None, fn)
  404.         else:
  405.             return (None, file_or_mod, fn)
  406.     else:
  407.         return (None, None, fn)
  408. split_test_name.__test__ = False # do not collect
  409.  
  410.  
  411. def test_address(test):
  412.     """Find the test address for a test, which may be a module, filename,
  413.     class, method or function.
  414.     """
  415.     if hasattr(test, "address"):
  416.         return test.address()
  417.     # type-based polymorphism sucks in general, but I believe is
  418.     # appropriate here
  419.     t = type(test)
  420.     file = module = call = None
  421.     if t == types.ModuleType:
  422.         file = getattr(test, '__file__', None)
  423.         module = getattr(test, '__name__', None)
  424.         return (src(file), module, call)
  425.     if t == types.FunctionType or issubclass(t, type) or t == types.ClassType:
  426.         module = getattr(test, '__module__', None)
  427.         if module is not None:
  428.             m = sys.modules[module]
  429.             file = getattr(m, '__file__', None)
  430.             if file is not None:
  431.                 file = os.path.abspath(file)
  432.         call = getattr(test, '__name__', None)
  433.         return (src(file), module, call)
  434.     if t == types.InstanceType:
  435.         return test_address(test.__class__)
  436.     if t == types.MethodType:
  437.         cls_adr = test_address(test.im_class)
  438.         return (src(cls_adr[0]), cls_adr[1],
  439.                 "%s.%s" % (cls_adr[2], test.__name__))
  440.     # handle unittest.TestCase instances
  441.     if isinstance(test, unittest.TestCase):
  442.         if hasattr(test, '_FunctionTestCase__testFunc'):
  443.             # unittest FunctionTestCase
  444.             return test_address(test._FunctionTestCase__testFunc)
  445.         # regular unittest.TestCase
  446.         cls_adr = test_address(test.__class__)
  447.         # 2.5 compat: __testMethodName changed to _testMethodName
  448.         try:
  449.             method_name = test._TestCase__testMethodName
  450.         except AttributeError:
  451.             method_name = test._testMethodName
  452.         return (src(cls_adr[0]), cls_adr[1],
  453.                 "%s.%s" % (cls_adr[2], method_name))
  454.     raise TypeError("I don't know what %s is (%s)" % (test, t))
  455. test_address.__test__ = False # do not collect
  456.  
  457.  
  458. def try_run(obj, names):
  459.     """Given a list of possible method names, try to run them with the
  460.     provided object. Keep going until something works. Used to run
  461.     setup/teardown methods for module, package, and function tests.
  462.     """
  463.     for name in names:
  464.         func = getattr(obj, name, None)
  465.         if func is not None:
  466.             if type(obj) == types.ModuleType:
  467.                 # py.test compatibility
  468.                 try:
  469.                     args, varargs, varkw, defaults = inspect.getargspec(func)
  470.                 except TypeError:
  471.                     # Not a function. If it's callable, call it anyway
  472.                     if hasattr(func, '__call__'):
  473.                         func = func.__call__
  474.                     try:
  475.                         args, varargs, varkw, defaults = \
  476.                             inspect.getargspec(func)
  477.                         args.pop(0) # pop the self off
  478.                     except TypeError:
  479.                         raise TypeError("Attribute %s of %r is not a python "
  480.                                         "function. Only functions or callables"
  481.                                         " may be used as fixtures." %
  482.                                         (name, obj))
  483.                 if len(args):
  484.                     log.debug("call fixture %s.%s(%s)", obj, name, obj)
  485.                     return func(obj)
  486.             log.debug("call fixture %s.%s", obj, name)
  487.             return func()
  488.  
  489.  
  490. def src(filename):
  491.     """Find the python source file for a .pyc, .pyo or $py.class file on
  492.     jython. Returns the filename provided if it is not a python source
  493.     file.
  494.     """
  495.     if filename is None:
  496.         return filename
  497.     if sys.platform.startswith('java') and filename.endswith('$py.class'):
  498.         return '.'.join((filename[:-9], 'py'))
  499.     base, ext = os.path.splitext(filename)
  500.     if ext in ('.pyc', '.pyo', '.py'):
  501.         return '.'.join((base, 'py'))
  502.     return filename
  503.  
  504.  
  505. def match_last(a, b, regex):
  506.     """Sort compare function that puts items that match a
  507.     regular expression last.
  508.  
  509.     >>> from nose.config import Config
  510.     >>> c = Config()
  511.     >>> regex = c.testMatch
  512.     >>> entries = ['.', '..', 'a_test', 'src', 'lib', 'test', 'foo.py']
  513.     >>> entries.sort(lambda a, b: match_last(a, b, regex))
  514.     >>> entries
  515.     ['.', '..', 'foo.py', 'lib', 'src', 'a_test', 'test']
  516.     """
  517.     if regex.search(a) and not regex.search(b):
  518.         return 1
  519.     elif regex.search(b) and not regex.search(a):
  520.         return -1
  521.     return cmp(a, b)
  522.  
  523.  
  524. def tolist(val):
  525.     """Convert a value that may be a list or a (possibly comma-separated)
  526.     string into a list. The exception: None is returned as None, not [None].
  527.  
  528.     >>> tolist(["one", "two"])
  529.     ['one', 'two']
  530.     >>> tolist("hello")
  531.     ['hello']
  532.     >>> tolist("separate,values, with, commas,  spaces , are    ,ok")
  533.     ['separate', 'values', 'with', 'commas', 'spaces', 'are', 'ok']
  534.     """
  535.     if val is None:
  536.         return None
  537.     try:
  538.         # might already be a list
  539.         val.extend([])
  540.         return val
  541.     except AttributeError:
  542.         pass
  543.     # might be a string
  544.     try:
  545.         return re.split(r'\s*,\s*', val)
  546.     except TypeError:
  547.         # who knows...
  548.         return list(val)
  549.  
  550.  
  551. class odict(dict):
  552.     """Simple ordered dict implementation, based on:
  553.  
  554.     http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
  555.     """
  556.     def __init__(self, *arg, **kw):
  557.         self._keys = []
  558.         super(odict, self).__init__(*arg, **kw)
  559.  
  560.     def __delitem__(self, key):
  561.         super(odict, self).__delitem__(key)
  562.         self._keys.remove(key)
  563.  
  564.     def __setitem__(self, key, item):
  565.         super(odict, self).__setitem__(key, item)
  566.         if key not in self._keys:
  567.             self._keys.append(key)
  568.  
  569.     def __str__(self):
  570.         return "{%s}" % ', '.join(["%r: %r" % (k, v) for k, v in self.items()])
  571.  
  572.     def clear(self):
  573.         super(odict, self).clear()
  574.         self._keys = []
  575.  
  576.     def copy(self):
  577.         d = super(odict, self).copy()
  578.         d._keys = self._keys[:]
  579.         return d
  580.  
  581.     def items(self):
  582.         return zip(self._keys, self.values())
  583.  
  584.     def keys(self):
  585.         return self._keys[:]
  586.  
  587.     def setdefault(self, key, failobj=None):
  588.         item = super(odict, self).setdefault(key, failobj)
  589.         if key not in self._keys:
  590.             self._keys.append(key)
  591.         return item
  592.  
  593.     def update(self, dict):
  594.         super(odict, self).update(dict)
  595.         for key in dict.keys():
  596.             if key not in self._keys:
  597.                 self._keys.append(key)
  598.  
  599.     def values(self):
  600.         return map(self.get, self._keys)
  601.  
  602.  
  603. def transplant_func(func, module):
  604.     """
  605.     Make a function imported from module A appear as if it is located
  606.     in module B.
  607.  
  608.     >>> from pprint import pprint
  609.     >>> pprint.__module__
  610.     'pprint'
  611.     >>> pp = transplant_func(pprint, __name__)
  612.     >>> pp.__module__
  613.     'nose.util'
  614.  
  615.     The original function is not modified.
  616.  
  617.     >>> pprint.__module__
  618.     'pprint'
  619.  
  620.     Calling the transplanted function calls the original.
  621.  
  622.     >>> pp([1, 2])
  623.     [1, 2]
  624.     >>> pprint([1,2])
  625.     [1, 2]
  626.  
  627.     """
  628.     from nose.tools import make_decorator
  629.     def newfunc(*arg, **kw):
  630.         return func(*arg, **kw)
  631.  
  632.     newfunc = make_decorator(func)(newfunc)
  633.     newfunc.__module__ = module
  634.     return newfunc
  635.  
  636.  
  637. def transplant_class(cls, module):
  638.     """
  639.     Make a class appear to reside in `module`, rather than the module in which
  640.     it is actually defined.
  641.  
  642.     >>> from nose.failure import Failure
  643.     >>> Failure.__module__
  644.     'nose.failure'
  645.     >>> Nf = transplant_class(Failure, __name__)
  646.     >>> Nf.__module__
  647.     'nose.util'
  648.     >>> Nf.__name__
  649.     'Failure'
  650.  
  651.     """
  652.     class C(cls):
  653.         pass
  654.     C.__module__ = module
  655.     C.__name__ = cls.__name__
  656.     return C
  657.  
  658.  
  659. def safe_str(val, encoding='utf-8'):
  660.     try:
  661.         return str(val)
  662.     except UnicodeEncodeError:
  663.         if isinstance(val, Exception):
  664.             return ' '.join([safe_str(arg, encoding)
  665.                              for arg in val])
  666.         return unicode(val).encode(encoding)
  667.  
  668.     
  669. if __name__ == '__main__':
  670.     import doctest
  671.     doctest.testmod()
  672.